using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace Basic_sprite_code
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class DarkLordsApprentice : Microsoft.Xna.Framework.Game
    {
        public GraphicsDeviceManager graphics;
        public SpriteBatch spriteBatch;
        public SpriteFont font;
        public SpriteFont font2;
        public KeyboardState keysCurrent;   // [KEN] currently pressed keys
        public KeyboardState keysPrevious;  // [KEN] previous " : this helps us track key presses (i.e. pressing a key and then letting go is a single action)
        public bool gamePaused;    // [KEN] bool for keeping track of paused state

        int gameCounter;
        int finalKills;
        

        StoryHelper gameStory;
        Background gameBackground;
        Apprentice player;
        Pointer playerPointer;
        MagicCircle playerCircle;

        public DarkLordsApprentice()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            keysCurrent = Keyboard.GetState();  // [KEN] ...
            keysPrevious = Keyboard.GetState(); // [KEN] Just have them the same initially. we need *somewhere* for previous to start

            gamePaused = false; // [KEN] when we start, it obviously should not be paused

            graphics.PreferredBackBufferWidth = 800;
            graphics.PreferredBackBufferHeight = 600;
            graphics.ApplyChanges();

            gameCounter = 0;
            finalKills = 0;

            gameBackground = new Background(this, new Vector2(0,0));
            Components.Add(gameBackground);
            
            gameStory = new StoryHelper(this, new Vector2(0, 0));
            
            player = new Apprentice(this, new Vector2(700, 550), gameStory);
            Components.Add(player);

            playerCircle = new MagicCircle(this, new Vector2(440, 590), player);
            Components.Add(playerCircle);

            player.setMagicCircle(playerCircle);

            Components.Add(new InterfaceBack(this, new Vector2(10,-5)));
            Components.Add(new MagicBar(this, new Vector2(10,-5), player));
            Components.Add(new EvilEye(this, new Vector2(10,-5), player));
            Components.Add(new InterfaceTop(this, new Vector2(10,-5)));

            Components.Add(gameStory);

            playerPointer = new Pointer(this, new Vector2(-100, -100));
            Components.Add(playerPointer);

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            // TODO: use this.Content to load your game content here
            font = Content.Load<SpriteFont>("Minion");
            font2 = Content.Load<SpriteFont>("font");
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // First, see what keys are pressed
            keysCurrent = Keyboard.GetState();

            // Allows the game to exit
            if (keysCurrent.IsKeyDown(Keys.Escape))
                this.Exit();
            
            // Toggle pause
            if (keysCurrent.IsKeyUp(Keys.P) && keysPrevious.IsKeyDown(Keys.P))
            {
                gamePaused = !gamePaused;
            }

            if (gameStory.playingGame && !gamePaused)
            {
                Random rand = new Random();
                int spawnSpot = 0;
                switch (player.evilnessLevel) {
                    case 1:
                        if (gameCounter % 150 == 0) {
                            spawnSpot = (int)(rand.NextDouble() * 600 + 100);
                            Components.Add(new Hero(this, new Vector2(spawnSpot, 160), player, 50, .50f));
                        }
                        break;
                    case 2:
                        if (gameCounter % 120 == 0) {
                            spawnSpot = (int)(rand.NextDouble() * 600 + 100);
                            Components.Add(new Hero(this, new Vector2(spawnSpot, 160), player, 55, .60f));
                        }
                        break;
                    case 3:
                        if (gameCounter % 90 == 0) {
                            spawnSpot = (int)(rand.NextDouble() * 600 + 100);
                            Components.Add(new Hero(this, new Vector2(spawnSpot, 160), player, 60, .75f));
                        }
                        break;
                    case 4:
                        if (gameCounter % 120 == 0) {
                            spawnSpot = (int)(rand.NextDouble() * 600 + 100);
                            Components.Add(new Hero(this, new Vector2(spawnSpot, 160), player, 50, .60f));
                            spawnSpot = (int)(rand.NextDouble() * 600 + 100);
                            Components.Add(new Hero(this, new Vector2(spawnSpot, 160), player, 50, .60f));
                        }
                        break;
                    case 5:
                        if (gameCounter % 100 == 0) {
                            spawnSpot = (int)(rand.NextDouble() * 600 + 100);
                            Components.Add(new Hero(this, new Vector2(spawnSpot, 160), player, 55, .75f));
                            spawnSpot = (int)(rand.NextDouble() * 600 + 100);
                            Components.Add(new Hero(this, new Vector2(spawnSpot, 160), player, 55, .75f));
                        }
                        break;
                    case 6:
                        if (gameCounter % 90 == 0) {
                            spawnSpot = (int)(rand.NextDouble() * 600 + 100);
                            Components.Add(new Hero(this, new Vector2(spawnSpot, 160), player, 60, .80f));
                            spawnSpot = (int)(rand.NextDouble() * 600 + 100);
                            Components.Add(new Hero(this, new Vector2(spawnSpot, 160), player, 55, .80f));
                        }
                        break;
                    case 7:
                        if (gameCounter % 110 == 0) {
                            spawnSpot = (int)(rand.NextDouble() * 600 + 100);
                            Components.Add(new Hero(this, new Vector2(spawnSpot, 160), player, 55, .60f));
                            spawnSpot = (int)(rand.NextDouble() * 600 + 100);
                            Components.Add(new Hero(this, new Vector2(spawnSpot, 160), player, 55, .60f));
                            spawnSpot = (int)(rand.NextDouble() * 600 + 100);
                            Components.Add(new Hero(this, new Vector2(spawnSpot, 160), player, 55, .60f));
                        }
                        if (gameCounter % 80 == 0) {
                            spawnSpot = (int)(rand.NextDouble() * 600 + 100);
                            Components.Add(new Hero(this, new Vector2(spawnSpot, 160), player, 50, .40f));
                        }
                        break;
                    case 8:
                        if (gameCounter % 140 == 0) {
                            spawnSpot = (int)(rand.NextDouble() * 600 + 100);
                            Components.Add(new Hero(this, new Vector2(spawnSpot, 160), player, 55, .75f));
                            spawnSpot = (int)(rand.NextDouble() * 600 + 100);
                            Components.Add(new Hero(this, new Vector2(spawnSpot, 160), player, 55, .75f));
                            spawnSpot = (int)(rand.NextDouble() * 600 + 100);
                            Components.Add(new Hero(this, new Vector2(spawnSpot, 160), player, 55, .75f));
                        }
                        if (gameCounter % 100 == 0) {
                            spawnSpot = (int)(rand.NextDouble() * 600 + 100);
                            Components.Add(new Hero(this, new Vector2(spawnSpot, 160), player, 50, .40f));
                            spawnSpot = (int)(rand.NextDouble() * 600 + 100);
                            Components.Add(new Hero(this, new Vector2(spawnSpot, 160), player, 50, .40f));
                        }
                        break;
                    case 9:
                        if (finalKills < 100) {
                            if (gameCounter % 130 == 0) {
                                spawnSpot = (int)(rand.NextDouble() * 600 + 100);
                                Components.Add(new Hero(this, new Vector2(spawnSpot, 160), player, 70, .45f));
                                spawnSpot = (int)(rand.NextDouble() * 600 + 100);
                                Components.Add(new Hero(this, new Vector2(spawnSpot, 160), player, 70, .75f));
                                spawnSpot = (int)(rand.NextDouble() * 600 + 100);
                                Components.Add(new Hero(this, new Vector2(spawnSpot, 160), player, 70, .60f));
                                spawnSpot = (int)(rand.NextDouble() * 600 + 100);
                                Components.Add(new Hero(this, new Vector2(spawnSpot, 160), player, 70, .75f));
                                finalKills += 3;
                            }
                            if (gameCounter % 200 == 0) {
                                spawnSpot = (int)(rand.NextDouble() * 600 + 100);
                                Components.Add(new Hero(this, new Vector2(spawnSpot, 160), player, 100, .30f));
                                spawnSpot = (int)(rand.NextDouble() * 600 + 100);
                                Components.Add(new Hero(this, new Vector2(spawnSpot, 160), player, 100, .30f));
                                finalKills += 1;
                            }
                        }
                        else {
                            int leftAlive = 0;
                            foreach (Sprite s in player.AllSprites)
                            {
                                if (s is Hero && !(s.position.X > 800 || s.position.X < 0 || s.position.Y > 600 || s.position.Y < 0))
                                {
                                leftAlive++;
                                }
                            }
                            if (leftAlive == 0)
                            {
                                gameStory.playingGame = false;
                                gameStory.gameWon = true;
                                finalKills = 0;
                                foreach (Sprite s in player.AllSprites)
                                {
                                    if (!(s is Background || s is StoryHelper))
                                    {
                                        s.position.X = 3000;
                                    }
                                }
                            }
                        }
                        break;
                }

                
            }


            // End-frame actions:
            gameCounter++;
            keysPrevious = keysCurrent; // [KEN] save keyboard state to previous
            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            // TODO: Add your drawing code here
            spriteBatch.Begin();
            base.Draw(gameTime);
            if (gameStory.playingGame)
            {
                spriteBatch.DrawString(font2, "Evilness Lv. " + player.evilnessLevel, new Vector2(66, 2), Color.BlanchedAlmond);
                spriteBatch.DrawString(font, player.currentMagic + "/" + player.maxMagic + "MP", new Vector2(68, 20), Color.BlanchedAlmond);
                
                // paused message
                if (gamePaused)
                    spriteBatch.DrawString(font2, "GAME PAUSED", new Vector2(300, 400), Color.White);
            }
            spriteBatch.End();
            
        }
    }
}
